using System.IO.Compression;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;

namespace UwinEducation.API.Middleware
{
    /// <summary>
    /// 响应压缩中间件，根据响应大小自动应用GZIP压缩
    /// </summary>
    public class ResponseCompressionMiddleware
    {
        private readonly RequestDelegate _next;
        private readonly ILogger<ResponseCompressionMiddleware> _logger;
        private const int MinCompressionSize = 50 * 1024; // 50KB

        public ResponseCompressionMiddleware(RequestDelegate next, ILogger<ResponseCompressionMiddleware> logger)
        {
            _next = next;
            _logger = logger;
        }

        public async Task InvokeAsync(HttpContext context)
        {
            var originalBodyStream = context.Response.Body;

            try
            {
                // 使用内存流来捕获响应
                using var memoryStream = new MemoryStream();
                context.Response.Body = memoryStream;

                // 调用下一个中间件
                await _next(context);

                // 检查响应大小
                var responseLength = memoryStream.Length;

                // 重置内存流位置
                memoryStream.Seek(0, SeekOrigin.Begin);

                // 如果响应大于最小压缩大小且客户端支持GZIP
                if (responseLength >= MinCompressionSize && 
                    context.Response.Headers.ContentType.ToString().Contains("application/json") &&
                    context.Request.Headers.AcceptEncoding.ToString().Contains("gzip"))
                {
                    _logger.LogInformation($"压缩响应，原始大小: {responseLength / 1024}KB");

                    // 设置GZIP压缩头
                    context.Response.Headers.ContentEncoding = "gzip";

                    // 使用异步方式处理GZIP压缩
                    using (var compressionStream = new GZipStream(originalBodyStream, CompressionLevel.Optimal, leaveOpen: true))
                    {
                        // 使用异步方式将内存流内容复制到GZIP流
                        await memoryStream.CopyToAsync(compressionStream);
                        // 确保所有数据都被刷新到底层流
                        await compressionStream.FlushAsync();
                    }
                }
                else
                {
                    // 直接将内存流内容复制到原始响应流
                    await memoryStream.CopyToAsync(originalBodyStream);
                }
            }
            finally
            {
                // 恢复原始响应流
                context.Response.Body = originalBodyStream;
            }
        }
    }

    /// <summary>
    /// 响应压缩中间件扩展
    /// </summary>
    public static class ResponseCompressionMiddlewareExtensions
    {
        public static IApplicationBuilder UseResponseCompression50KB(this IApplicationBuilder builder)
        {
            return builder.UseMiddleware<ResponseCompressionMiddleware>();
        }
    }
} 